/*
 * dsmRequestor.cpp
 *
 *  Created on: Dec 15, 2013
 *      Author: m
 */

#include <cstring>
#include "DSMComun.h"
#include "SharedMemory2.h"
#include "MessageQueue.h"
#include "ColaRemotaTransmisor.h"
#include "ColaRemotaReceptor.h"
#include "CPrinter.h"
#include "StringUtils.h"
#include "Robot11AProductor.h"
#include "Cinta15.h"
#include "Cinta13B.h"
#include "Cinta13A.h"
#include "Robot11BProductor.h"
#include "Robot14Consumidor.h"
#include "Robot14Productor.h"
#include "Robot16Consumidor.h"

using ipc::MessageQueue;
using ipc::CPrinter;
using ipc::SharedMemory2;

int main ( int argc, char* argv[] )
{
    std::string requestorName;
    std::string colaRespuesta;

    CPrinter::setHeader( "dsmRequestor" );

    if ( argc != 2 )
    {
        CPrinter::printErr( "Cantidad de argumentos invalidos" );
        exit( 1 );
    }

    requestorName = argv[1];

    CPrinter::setHeader( "dsmRequestor " + requestorName );

    colaRespuesta = requestorName + ".dsmresp";

    MessageQueue<PedidoDSM> colaPedidos =
            MessageQueue<PedidoDSM>::get( requestorName + "shm.ipc", COLA_PEDIDO_HOST );
    MessageQueue<TokenDSM> colaEntrega =
            MessageQueue<TokenDSM>::get( requestorName + "shm.ipc", COLA_ENTREGA_HOST );

    // Creo los transmisores y receptores de mensajes de DSM
    ColaRemotaTransmisor transmisor;
    ColaRemotaReceptor receptor( colaRespuesta );

    while ( true )
    {
        std::string colaDestino;
        PedidoDSM  pedido;
        TokenDSM entrega;

        pedido = colaPedidos.get( 0 );

        CPrinter::printOut( "Enviando pedido con shmid: %d", pedido.idDSM );

        strcpy( pedido.colaRespuesta, colaRespuesta.c_str() );

        colaDestino = COLA_PEDIDO_BROKER_BASENAME + StringUtils::NumberToString( pedido.idDSM );

        transmisor.enviarMensaje<PedidoDSM>( colaDestino, pedido );

        CPrinter::printOut( "Esperando Token: %d", pedido.idDSM );
        entrega = receptor.recibirMensaje<TokenDSM>();
        CPrinter::printOut( "Recibi el Token: %d", entrega.idDSM );

        CPrinter::printOut( "Actualizando la shmem: %d", entrega.idDSM );

        switch ( entrega.idDSM )
        {
            case DSMID_TEST:
            {
                ContadorDistribuido *p = SharedMemory2<ContadorDistribuido>::get( DSM_IPC_BASEFILE, SHM_TEST );
                memcpy( p, entrega.data, sizeof(ContadorDistribuido) );
            }
                break;

            case DSMID_CINTA13A:
            {
                Cinta3Slots *p = SharedMemory2<Cinta3Slots>::get( Cinta13A::s_ipcBaseFile, Cinta13A::s_cintaKey );
                memcpy( p, entrega.data, sizeof(Cinta3Slots) );
            }
                break;

            case DSMID_CINTA13B:
            {
                Cinta3Slots *p = SharedMemory2<Cinta3Slots>::get( Cinta13B::s_ipcBaseFile, Cinta13B::s_cintaKey );
                memcpy( p, entrega.data, sizeof(Cinta3Slots) );
            }
                break;

            case DSMID_CINTA15:
            {
                Cinta5Slots *p = SharedMemory2<Cinta5Slots>::get( Cinta15::s_ipcBaseFile, Cinta15::s_cintaKey );
                memcpy( p, entrega.data, sizeof(Cinta5Slots) );
            }
                break;

            case DSMID_R11APROD:
            {
                bool *p = SharedMemory2<bool>::get( Robot11AProductor::s_ipcBaseFile, Robot11AProductor::s_esperaEspacioKey );
                memcpy( p, entrega.data, sizeof(bool) );
            }
                break;

            case DSMID_R11BPROD:
            {
                bool *p = SharedMemory2<bool>::get( Robot11BProductor::s_ipcBaseFile, Robot11BProductor::s_esperaEspacioKey );
                memcpy( p, entrega.data, sizeof(bool) );
            }
                break;

            case DSMID_R14CONS:
            {
                bool *p = SharedMemory2<bool>::get( Robot14Consumidor::s_ipcBaseFile, Robot14Consumidor::s_esperaProductoKey );
                memcpy( p, entrega.data, sizeof(bool) );
            }
                break;

            case DSMID_R14PROD:
            {
                bool *p = SharedMemory2<bool>::get( Robot14Productor::s_ipcBaseFile, Robot14Productor::s_esperaEspacioKey );
                memcpy( p, entrega.data, sizeof(bool) );
            }
                break;

            case DSMID_R16CONS:
            {
                bool *p = SharedMemory2<bool>::get( Robot16Consumidor::s_ipcBaseFile, Robot16Consumidor::s_esperaProductoKey );
                memcpy( p, entrega.data, sizeof(bool) );
            }
                break;

            default:
                throw Exception( "DSM: Unknown DSMID" );
                break;
        }

        CPrinter::printOut( "Entregando el token a: %s", requestorName.c_str() );
        colaEntrega.put( entrega.idDSM, entrega );
    }

    return 0;
}
